import { action, makeAutoObservable } from 'mobx';
import UiState from './UiState';

class ModalState {
    editedSuite = null;

    renameState = {};

    importSuiteState = {};

    suiteSettingsState = {};

    baseUrlState = {};

    welcomeState = {
        started: false,
        completed: false,
    };

    newWindowConfigurationState = false;

    exportState = {};

    constructor() {
        this.renameTest = this.rename.bind(this, Types.test);
        this.renameSuite = this.rename.bind(this, Types.suite);
        this.rename = this.rename.bind(this);
        this.exportPayload = undefined;
        makeAutoObservable(this, {}, { autoBind: true });
    }

    selectBaseUrl(options = { isInvalid: true }) {
        return new Promise((res, rej) => {
            this.baseUrlState = {
                ...options,
                selecting: true,
                done: action((url) => {
                    res(url);
                    this.baseUrlState = {};
                }),
                cancel: action(() => {
                    rej();
                    this.baseUrlState = {};
                }),
            };
        });
    }

    rename(type, value, opts = { isNewTest: false }) {
        const verifyName = (name) => {
            let names;
            if (type === Types.test) names = UiState._project.tests;
            else if (type === Types.suite) names = UiState._project.suites;

            return name === value || this.nameIsUnique(name, names);
        };
        return new Promise((res) => {
            this.renameState = {
                original: value,
                value,
                type,
                verify: verifyName,
                isNewTest: opts.isNewTest,
                done: (name) => {
                    if (verifyName(name)) {
                        res(name);
                        if (type === Types.test) {
                            this.renameRunCommands(this.renameState.original, name);
                        }
                        this.cancelRenaming();
                    }
                },
                cancel: () => {
                    this.cancelRenaming();
                    if (!this.welcomeState.completed) this.showWelcome();
                },
            };
        });
    }

    editSuite(suite) {
        this.editedSuite = suite;
    }

    cancelRenaming() {
        this.renameState = {};
    }

    createSuite() {
        this.renameSuite(undefined).then((name) => {
            if (name) this._project.createSuite(name);
        });
    }

    createTest() {
        this.renameTest(undefined).then((name) => {
            if (name) {
                const test = this._project.createTestCase(name);
                UiState.selectTest(test);
            }
        });
    }

    async deleteSuite(suite) {
        const choseDelete = await this.showAlert({
            title: 'Delete suite',
            description: `This will permanently delete '${suite.name}'`,
            cancelLabel: 'cancel',
            confirmLabel: 'delete',
        });
        if (choseDelete) {
            this._project.deleteSuite(suite);
            UiState.selectTest();
        }
    }

    async deleteTest(testCase) {
        const choseDelete = await this.showAlert({
            title: 'Delete test case',
            description: `This will permanently delete '${testCase.name}', and remove it from all its suites`,
            cancelLabel: 'cancel',
            confirmLabel: 'delete',
        });
        if (choseDelete) {
            this._project.deleteTestCase(testCase);
            UiState.selectTest();
        }
    }

    async codeExport(payload) {
        this.exportState = { isExporting: true };
        this.exportPayload = payload;
    }

    async cancelCodeExport() {
        this.exportState = {};
        this.exportPayload = undefined;
    }

    importSuite(suite, onComplete) {
        this.importSuiteState = {
            suite,
            onComplete: (...argv) => {
                this.cancelImport();
                onComplete(...argv);
            },
        };
    }

    cancelImport() {
        this.importSuiteState = {};
    }

    editSuiteSettings(suite) {
        this.suiteSettingsState = {
            editing: true,
            isParallel: suite.isParallel,
            persistSession: suite.persistSession,
            timeout: suite.timeout,
            done: ({ isParallel, persistSession, timeout }) => {
                suite.setTimeout(timeout);
                suite.setParallel(isParallel);
                suite.setPersistSession(persistSession);
                this.cancelSuiteSettings();
            },
        };
    }

    cancelSuiteSettings() {
        this.suiteSettingsState = {};
    }

    nameIsUnique(value, list) {
        if (list) {
            return !list.find(({ name }) => name === value);
        } else {
            return true;
        }
    }

    renameRunCommands(original, newName) {
        UiState._project.tests.forEach((test) => {
            test.commands.forEach((command) => {
                if (command.command === 'run' && command.target === original) {
                    command.setTarget(newName);
                }
            });
        });
    }

    showWelcome() {
        this.welcomeState = { started: false, completed: false };
    }

    hideWelcome() {
        this.welcomeState = { started: true, completed: false };
    }

    completeWelcome() {
        this.welcomeState = { started: true, completed: true };
    }

    renameProject() {
        return this.rename(Types.project, this._project.name);
    }

    toggleNewWindowConfiguration() {
        this.newWindowConfigurationState = !this.newWindowConfigurationState;
    }

    isUniqueWindowName(windowName, commandId) {
        const commands = UiState.selectedTest.test.commands
            .filter((command) => command.id !== commandId)
            .filter((command) => command.windowHandleName !== '')
            .map((command) => command.windowHandleName);
        return !commands.includes(windowName);
    }
}

const Types = {
    test: 'test case',
    suite: 'suite',
    project: 'project',
};

if (!window._modalState) window._modalState = new ModalState();

export default window._modalState;
